<template>
  <div class="role-resource-list">
    <Spin :spinning="loading">
      <List
        class="resource-list"
        :dataSource="resources"
        :rowKey="(item) => item.id.toString()"
      >
        <template #renderItem="{ item }">
          <ListItem>
            <div class="resource-item">
              <div class="resource-header">
                <Checkbox
                  :checked="item.isSelected"
                  @change="(e) => handleResourceSelect(item, e.target.checked)"
                >
                  <span class="resource-name">{{ item.name }}</span>
                </Checkbox>
                <div class="resource-code">{{ item.code }}</div>
              </div>

              <div v-if="item.isSelected" class="resource-operations mt-2">
                <div class="operation-checkboxes">
                  <Checkbox
                    v-if="item.isSelected"
                    :checked="checkAll(item)"
                    @change="(e) => handleCheckAll(item, e.target.checked)"
                    class="check-all-box"
                    >全选：</Checkbox
                  >
                  <Checkbox
                    v-for="op in item.allowedOperations"
                    :key="op.code"
                    :checked="isOperationSelected(item, op.code)"
                    @change="
                      (e) =>
                        handleOperationSelect(item, op.code, e.target.checked)
                    "
                    class="operation-checkbox"
                  >
                    {{ op.display }}
                  </Checkbox>
                </div>
              </div>
            </div>
          </ListItem>
        </template>
      </List>
    </Spin>
  </div>
</template>

<script lang="ts" setup>
import { List, ListItem, Checkbox, Spin } from 'ant-design-vue';
import { type ResourceNode } from '#/api/daprplus/auth/role-authorize';
import { ref, watch } from 'vue';
import {
  isOperationSelected,
  handleResourceSelect as handleResourceSelectUtil,
  handleOperationSelect as handleOperationSelectUtil,
  checkResourceChanges,
  saveResourceOriginalState,
} from '#/utils/daprplus';

const props = defineProps<{
  resources: ResourceNode[];
  loading: boolean;
  serviceKey: string;
}>();

const emit = defineEmits<{
  'update:resources': [resources: ResourceNode[]];
  'resource-selected': [resource: ResourceNode, selected: boolean];
  'operation-selected': [
    resource: ResourceNode,
    operation: string,
    selected: boolean,
  ];
  'has-changes': [serviceKey: string, hasChanges: boolean];
}>();

// 存储资源的原始状态，用于检测变更
const originalResourcesState = ref<
  Map<string, { isSelected: boolean; operations: string[] }>
>(new Map());

// 计算属性：检查当前资源的所有操作是否全部选中
const checkAll = (item: ResourceNode) => {
  if (
    !item.isSelected ||
    !item.allowedOperations ||
    item.allowedOperations.length === 0
  ) {
    return false;
  }
  return item.allowedOperations.every((op) =>
    isOperationSelected(item, op.code),
  );
};

// 处理全选/取消全选
const handleCheckAll = (item: ResourceNode, checked: boolean) => {
  if (!item.isSelected || !item.allowedOperations) return;

  item.allowedOperations.forEach((op) => {
    handleOperationSelect(item, op.code, checked);
  });
};

// 监听资源变化，保存原始状态
watch(
  () => props.resources,
  (newResources) => {
    if (newResources && !props.loading) {
      originalResourcesState.value = saveResourceOriginalState(newResources);
    }
  },
  { immediate: true },
);

// 处理资源选择
function handleResourceSelect(resource: ResourceNode, selected: boolean) {
  // 使用工具函数更新资源
  handleResourceSelectUtil(resource, selected);

  // 触发事件
  emit('resource-selected', resource, selected);

  // 检查变更并通知父组件
  const hasChanges = checkResourceChanges(
    props.resources,
    originalResourcesState.value,
  );
  emit('has-changes', props.serviceKey, hasChanges);
}

// 处理操作选择
function handleOperationSelect(
  resource: ResourceNode,
  operation: string,
  selected: boolean,
) {
  // 使用工具函数更新资源
  handleOperationSelectUtil(resource, operation, selected);

  // 触发事件
  emit('operation-selected', resource, operation, selected);

  // 检查变更并通知父组件
  const hasChanges = checkResourceChanges(
    props.resources,
    originalResourcesState.value,
  );
  emit('has-changes', props.serviceKey, hasChanges);
}

// 暴露方法给父组件
defineExpose({
  hasChanges: () =>
    checkResourceChanges(props.resources, originalResourcesState.value),
  resetOriginalState: () => {
    originalResourcesState.value = saveResourceOriginalState(props.resources);
  },
});
</script>

<style scoped>
.role-resource-list {
  padding: 0 10px;
}

.resource-item {
  width: 100%;
}

.resource-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.resource-name {
  font-weight: bold;
}

.resource-code {
  color: #999;
  font-size: 12px;
}

.resource-operations {
  background-color: #f0f0f0;
  border-radius: 2px;
  padding: 4px;
}

.operation-checkboxes {
  display: flex;
  flex-wrap: wrap;
  gap: 0px;
}

.check-all-box {
  background-color: #e6e6e6;
  padding: 0 4px;
  border-radius: 2px;
}

.operation-checkbox {
  background-color: #ffffff;
  padding: 0 4px;
  border-radius: 2px;
  box-shadow: 0 0 0 1px #e8e8e8;
}
</style>
